home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / site-packages / gtk-2.0 / dsextras.py < prev    next >
Text File  |  2006-01-20  |  12KB  |  345 lines

  1. #
  2. # dsextras.py - Extra classes and utilities
  3. #
  4. # TODO:
  5. # Make it possible to import codegen from another dir
  6. #
  7.  
  8. from distutils.command.build_ext import build_ext
  9. from distutils.command.install_lib import install_lib
  10. from distutils.command.install_data import install_data
  11. from distutils.extension import Extension
  12. import fnmatch
  13. import os
  14. import re
  15. import string
  16. import sys
  17.  
  18. GLOBAL_INC = []
  19. GLOBAL_MACROS = []
  20.  
  21. def get_m4_define(varname):
  22.     """Return the value of a m4_define variable as set in configure.in."""
  23.     pattern=re.compile("m4_define\("+varname+"\,\s*(.+)\)")
  24.     for line in open("configure.in").readlines():
  25.         match_obj=pattern.match(line)
  26.         if match_obj:
  27.             return match_obj.group(1)
  28.  
  29.     return None
  30.  
  31. def getoutput(cmd):
  32.     """Return output (stdout or stderr) of executing cmd in a shell."""
  33.     return getstatusoutput(cmd)[1]
  34.  
  35. def getstatusoutput(cmd):
  36.     """Return (status, output) of executing cmd in a shell."""
  37.     if sys.platform == 'win32':
  38.         pipe = os.popen(cmd, 'r')
  39.         text = pipe.read()
  40.         sts = pipe.close() or 0
  41.         if text[-1:] == '\n':
  42.             text = text[:-1]
  43.         return sts, text
  44.     else:
  45.         from commands import getstatusoutput
  46.         return getstatusoutput(cmd)
  47.  
  48. def have_pkgconfig():
  49.     """Checks for the existence of pkg-config"""
  50.     if (sys.platform == 'win32' and
  51.         os.system('pkg-config --version > NUL') == 0):
  52.         return 1
  53.     else:
  54.         if getstatusoutput('pkg-config')[0] == 256:
  55.             return 1
  56.  
  57. def list_files(dir):
  58.     """List all files in a dir, with filename match support:
  59.     for example: glade/*.glade will return all files in the glade directory
  60.     that matches *.glade. It also looks up the full path"""
  61.     if dir.find(os.sep) != -1:
  62.         parts = dir.split(os.sep)
  63.         dir = string.join(parts[:-1], os.sep)
  64.         pattern = parts[-1]
  65.     else:
  66.         pattern = dir
  67.         dir = '.'
  68.  
  69.     dir = os.path.abspath(dir)
  70.     retval = []
  71.     for file in os.listdir(dir):
  72.         if fnmatch.fnmatch(file, pattern):
  73.             retval.append(os.path.join(dir, file))
  74.     return retval
  75.  
  76. def pkgc_version_check(name, longname, req_version):
  77.     is_installed = not os.system('pkg-config --exists %s' % name)
  78.     if not is_installed:
  79.         print "Could not find %s" % longname
  80.         return 0
  81.     
  82.     orig_version = getoutput('pkg-config --modversion %s' % name)
  83.     version = map(int, orig_version.split('.'))
  84.     pkc_version = map(int, req_version.split('.'))
  85.                       
  86.     if version >= pkc_version:
  87.         return 1
  88.     else:
  89.         print "Warning: Too old version of %s" % longname
  90.         print "         Need %s, but %s is installed" % \
  91.               (pkc_version, orig_version)
  92.         self.can_build_ok = 0
  93.         return 0
  94.  
  95. class BuildExt(build_ext):
  96.     def init_extra_compile_args(self):
  97.         self.extra_compile_args = []
  98.         if sys.platform == 'win32' and \
  99.            self.compiler.compiler_type == 'mingw32':
  100.             # MSVC compatible struct packing is required.
  101.             # Note gcc2 uses -fnative-struct while gcc3 
  102.             # uses -mms-bitfields. Based on the version
  103.             # the proper flag is used below.
  104.             msnative_struct = { '2' : '-fnative-struct',
  105.                                 '3' : '-mms-bitfields' }
  106.             gcc_version = getoutput('gcc -dumpversion')
  107.             print 'using MinGW GCC version %s with %s option' % \
  108.                   (gcc_version, msnative_struct[gcc_version[0]])
  109.             self.extra_compile_args.append(msnative_struct[gcc_version[0]])
  110.     
  111.     def modify_compiler(self):
  112.         if sys.platform == 'win32' and \
  113.            self.compiler.compiler_type == 'mingw32':
  114.             # Remove '-static' linker option to prevent MinGW ld
  115.             # from trying to link with MSVC import libraries.
  116.             if self.compiler.linker_so.count('-static'):
  117.                 self.compiler.linker_so.remove('-static')
  118.     
  119.     def build_extensions(self):
  120.         # Init self.extra_compile_args
  121.         self.init_extra_compile_args()
  122.         # Modify default compiler settings
  123.         self.modify_compiler()
  124.         # Invoke base build_extensions()
  125.         build_ext.build_extensions(self)
  126.         
  127.     def build_extension(self, ext):
  128.         # Add self.extra_compile_args to ext.extra_compile_args
  129.         ext.extra_compile_args += self.extra_compile_args
  130.         # Generate eventual templates before building
  131.         if hasattr(ext, 'generate'):
  132.             ext.generate()
  133.         # Invoke base build_extension()
  134.         build_ext.build_extension(self, ext)
  135.  
  136. class InstallLib(install_lib):
  137.  
  138.     local_outputs = []
  139.     local_inputs = []
  140.         
  141.     def set_install_dir(self, install_dir):
  142.         self.install_dir = install_dir
  143.     
  144.     def get_outputs(self):
  145.         return install_lib.get_outputs(self) + self.local_outputs
  146.  
  147.     def get_inputs(self):
  148.         return install_lib.get_inputs(self) + self.local_inputs
  149.  
  150. class InstallData(install_data):
  151.     
  152.     local_outputs = []
  153.     local_inputs = []
  154.     template_options = {}
  155.  
  156.     def prepare(self):
  157.         if os.name == "nt":
  158.             self.prefix = os.sep.join(self.install_dir.split(os.sep)[:-3])
  159.         else:
  160.             # default: os.name == "posix"
  161.             self.prefix = os.sep.join(self.install_dir.split(os.sep)[:-4])
  162.  
  163.         self.exec_prefix = '${prefix}/bin'
  164.         self.includedir = '${prefix}/include'
  165.         self.libdir = '${prefix}/lib'
  166.         self.datadir = '${prefix}/share'
  167.         
  168.         self.add_template_option('prefix', self.prefix)        
  169.         self.add_template_option('exec_prefix', self.exec_prefix)        
  170.         self.add_template_option('includedir', self.includedir)
  171.         self.add_template_option('libdir', self.libdir)
  172.         self.add_template_option('datadir', self.datadir)
  173.         self.add_template_option('PYTHON', sys.executable)
  174.         self.add_template_option('THREADING_CFLAGS', '')
  175.         
  176.     def set_install_dir(self, install_dir):
  177.         self.install_dir = install_dir
  178.         
  179.     def add_template_option(self, name, value):
  180.         self.template_options['@%s@' % name] = value
  181.  
  182.     def install_template(self, filename, install_dir):
  183.         """Install template filename into target directory install_dir."""
  184.         output_file = os.path.split(filename)[-1][:-3]
  185.  
  186.         template = open(filename).read()
  187.         for key, value in self.template_options.items():
  188.             template = template.replace(key, value)
  189.         
  190.         output = os.path.join(install_dir, output_file)
  191.         self.mkpath(install_dir)
  192.         open(output, 'w').write(template)
  193.         self.local_inputs.append(filename)
  194.         self.local_outputs.append(output)
  195.         return output
  196.     
  197.     def get_outputs(self):
  198.         return install_lib.get_outputs(self) + self.local_outputs
  199.  
  200.     def get_inputs(self):
  201.         return install_lib.get_inputs(self) + self.local_inputs
  202.     
  203. class PkgConfigExtension(Extension):
  204.     can_build_ok = None
  205.     def __init__(self, **kwargs):
  206.         name = kwargs['pkc_name']
  207.         kwargs['include_dirs'] = self.get_include_dirs(name) + GLOBAL_INC
  208.         kwargs['define_macros'] = GLOBAL_MACROS
  209.         kwargs['libraries'] = self.get_libraries(name)
  210.         kwargs['library_dirs'] = self.get_library_dirs(name)
  211.         self.name = kwargs['name']
  212.         self.pkc_name = kwargs['pkc_name']
  213.         self.pkc_version = kwargs['pkc_version']
  214.         del kwargs['pkc_name'], kwargs['pkc_version']
  215.         Extension.__init__(self, **kwargs)
  216.  
  217.     def get_include_dirs(self, name):
  218.         output = getoutput('pkg-config --cflags-only-I %s' % name)
  219.         return output.replace('-I', '').split()
  220.  
  221.     def get_libraries(self, name):
  222.         output = getoutput('pkg-config --libs-only-l %s' % name)
  223.         return output.replace('-l', '').split()
  224.     
  225.     def get_library_dirs(self, name):
  226.         output = getoutput('pkg-config --libs-only-L %s' % name)
  227.         return output.replace('-L', '').split()
  228.  
  229.     def can_build(self):
  230.         """If the pkg-config version found is good enough"""
  231.         if self.can_build_ok != None: 
  232.             return self.can_build_ok
  233.  
  234.         retval = os.system('pkg-config --exists %s' % self.pkc_name)
  235.         if retval:
  236.             print ("* %s.pc could not be found, bindings for %s"
  237.                    " will not be built." % (self.pkc_name, self.name))
  238.             self.can_build_ok = 0
  239.             return 0
  240.  
  241.         orig_version = getoutput('pkg-config --modversion %s' % self.pkc_name)
  242.         version = map(int, orig_version.split('.'))
  243.         pkc_version = map(int, self.pkc_version.split('.'))
  244.                       
  245.         if version >= pkc_version:
  246.             self.can_build_ok = 1
  247.             return 1
  248.         else:
  249.             print "Warning: Too old version of %s" % self.pkc_name
  250.             print "         Need %s, but %s is installed" % \
  251.                   (self.pkc_version, orig_version)
  252.             self.can_build_ok = 0
  253.             return 0
  254.         
  255.     def generate(self):
  256.         pass
  257.        
  258. class Template:
  259.     def __init__(self, override, output, defs, prefix,
  260.                  register=[], load_types=None):
  261.         self.override = override
  262.         self.defs = defs
  263.         self.register = register
  264.         self.output = output
  265.         self.prefix = prefix
  266.         self.load_types = load_types
  267.         
  268.     def check_dates(self):
  269.         if not os.path.exists(self.output):
  270.             return 0
  271.  
  272.         files = self.register[:]
  273.         files.append(self.override)
  274. #        files.append('setup.py')
  275.         files.append(self.defs)
  276.         
  277.         newest = 0
  278.         for file in files:
  279.             test = os.stat(file)[8]
  280.             if test > newest:
  281.                 newest = test
  282.                 
  283.         if newest < os.stat(self.output)[8]:
  284.             return 1
  285.         return 0
  286.     
  287.     def generate(self):
  288.         # We must insert it first, otherwise python will try '.' first,
  289.         # in which it exist a "bogus" codegen (the third import line
  290.         # here will fail)
  291.         sys.path.insert(0, 'codegen')
  292.         from override import Overrides
  293.         from defsparser import DefsParser
  294.         from codegen import register_types, write_source, FileOutput
  295.         
  296.         if self.check_dates():
  297.             return
  298.  
  299.         for item in self.register:
  300.             dp = DefsParser(item)
  301.             dp.startParsing()
  302.             register_types(dp)
  303.  
  304.         if self.load_types:
  305.             globals = {}
  306.             execfile(self.load_types, globals)
  307.             
  308.         dp = DefsParser(self.defs)
  309.         dp.startParsing()
  310.         register_types(dp)
  311.         
  312.         fd = open(self.output, 'w')
  313.         write_source(dp,
  314.                      Overrides(self.override),
  315.                      self.prefix,
  316.                      FileOutput(fd, self.output))
  317.         fd.close()
  318.         
  319. class TemplateExtension(PkgConfigExtension):
  320.     def __init__(self, **kwargs):
  321.         name = kwargs['name']
  322.         defs = kwargs['defs']
  323.         output = defs[:-5] + '.c'
  324.         override = kwargs['override']
  325.         load_types = kwargs.get('load_types')
  326.         self.templates = []
  327.         self.templates.append(Template(override, output, defs, 'py' + name,
  328.                                        kwargs['register'], load_types))
  329.         
  330.         del kwargs['register'], kwargs['override'], kwargs['defs']
  331.         if load_types:
  332.            del kwargs['load_types']
  333.            
  334.         if kwargs.has_key('output'):
  335.             kwargs['name'] = kwargs['output']
  336.             del kwargs['output']
  337.         
  338.         PkgConfigExtension.__init__(self, **kwargs)
  339.         
  340.     def generate(self):
  341.         map(lambda x: x.generate(), self.templates)
  342.         
  343.         
  344.  
  345.